package org.breathe.dynamic.thread.pool.core.notify.alarm;

import lombok.extern.slf4j.Slf4j;
import org.breathe.dynamic.thread.pool.core.context.BreatheDtpContext;
import org.breathe.dynamic.thread.pool.core.context.BreatheDtpContextHolder;
import org.breathe.dynamic.thread.pool.core.designpattern.strategy.AlarmStrategy;
import org.breathe.dynamic.thread.pool.core.designpattern.strategy.impl.alarmstrategy.CapacityAlarmStrategy;
import org.breathe.dynamic.thread.pool.core.designpattern.strategy.impl.alarmstrategy.LivenessAlarmStrategy;
import org.breathe.dynamic.thread.pool.core.designpattern.strategy.impl.alarmstrategy.RejectAlarmStrategy;
import org.breathe.dynamic.thread.pool.core.handler.NotifierHandler;
import org.breathe.dynamic.thread.pool.core.notify.NotifyHelper;
import org.breathe.dynamic.thread.pool.core.thread.BreatheDtpExecutor;
import org.breathe.dynamic.thread.pool.core.thread.ThreadPoolBuilder;
import org.breathe.thread.pool.common.constant.BreatheDtpConstant;
import org.breathe.thread.pool.common.entity.BreatheDtpProperties;
import org.breathe.thread.pool.common.entity.NotifyItem;
import org.breathe.thread.pool.common.enums.NotifyTypeEnum;
import org.breathe.thread.pool.common.enums.QueueTypeEnum;
import org.breathe.thread.pool.common.enums.RejectedTypeEnum;
import org.breathe.thread.pool.common.utils.ApplicationContextHolder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * 警报管理
 * @author: breathe
 * @createTime: 2025-04-13
 */
@Slf4j
public class AlarmManager {
    /**
     * 报警的线程池
     * 通过ThreadPoolBuilder来建造，保证被动态线程池管理
     */
    private static final ExecutorService ALARM_EXECUTOR = ThreadPoolBuilder.newBuilder()
            .threadPoolName(BreatheDtpConstant.ALARM_EXECUTOR_PREFIX)
            .threadFactory(BreatheDtpConstant.ALARM_EXECUTOR_PREFIX)
            .corePoolSize(5)
            .maximumPoolSize(10)
            .workQueue(QueueTypeEnum.VARIABLE_LINKED_BLOCKING_QUEUE.getName(), 2000, false)
            .rejectedExecutionHandler(RejectedTypeEnum.ABORT_POLICY.getName())
            .buildWithTtl();
    /**
     * 策略
     */
    private static final Map<NotifyTypeEnum, AlarmStrategy> STRATEGY_MAP = new HashMap<>();

    static {
        STRATEGY_MAP.put(NotifyTypeEnum.REJECT, new RejectAlarmStrategy());
        STRATEGY_MAP.put(NotifyTypeEnum.CAPACITY, new CapacityAlarmStrategy());
        STRATEGY_MAP.put(NotifyTypeEnum.LIVENESS, new LivenessAlarmStrategy());
    }
    private AlarmManager() {}

    /**
     * 触发报警
     * @param runnable 报警要执行的方法
     */
    public static void triggerAlarm(Runnable runnable) {
        ALARM_EXECUTOR.submit(runnable);
    }

    /**
     * 触发报警
     * @param dtpName
     * @param notifyType
     * @param runnable
     */
    public static void triggerAlarm(String dtpName, String notifyType, Runnable runnable) {
        AlarmCounter.incAlarmCounter(dtpName, notifyType);
        ALARM_EXECUTOR.execute(runnable);
    }
    /**
     * 发送报警
     * @param executor 动态线程池
     * @param typeEnums 所有报警类型
     */
    public static void doAlarm(BreatheDtpExecutor executor, List<NotifyTypeEnum> typeEnums) {
        typeEnums.forEach(each -> doAlarm(executor, each));
    }

    /**
     * 发送报警
     * @param executor 线程池
     * @param typeEnum 报警类型
     */
    public static void doAlarm(BreatheDtpExecutor executor, NotifyTypeEnum typeEnum) {
        //从这个map结构获取执行策略
        AlarmStrategy strategy = STRATEGY_MAP.get(typeEnum);
        if (strategy == null) {
            log.warn("No strategy found for type: {}", typeEnum.getValue());
            return ;
        }

        NotifyItem notifyItem = NotifyHelper.getNotifyItem(executor, typeEnum);
        if (!strategy.check(executor, notifyItem)) {
            return ;
        }

        //通过报警限制中的cache判断是否需要报警。
        boolean ifAlarm = AlarmLimiter.ifAlarm(executor, typeEnum.getValue());
        if (!ifAlarm) {
            log.warn("breathe dynamic thread pool notify, alarm limit, breathe dynamicTp Name: {}, type: {}", executor.getThreadPoolName(), typeEnum.getValue());
            return ;
        }
        //发送报警，并添加到cache中。
        BreatheDtpProperties breatheDtpProperties = ApplicationContextHolder.getBean(BreatheDtpProperties.class);
        BreatheDtpContext breatheDtpContext = BreatheDtpContext.builder()
                .breatheDtpExecutor(executor)
                .platforms(breatheDtpProperties.getPlatforms())
                .notifyItem(notifyItem)
                .build();
        BreatheDtpContextHolder.set(breatheDtpContext);
        AlarmLimiter.putVal(executor, typeEnum.getValue());
        NotifierHandler.getInstance().sendAlarm(typeEnum);
    }
}